/** @file core.h
 *
 * @brief LSUP_REPO core module.
 */

#ifndef _LSR_CORE_H
#define _LSR_CORE_H

// TODO Include hashmap.c in lsup_rdf and remove this header dep.
#include "hashmap.h"

#include "lsup_rdf.h"


/*
 * Defines.
 */

/// URI prefix for all managed resources.
#define LSR_RSRC_PFX "urn:lsres:"

/// Label for descriptive resource type.
#define LSR_TYPE_DESC "DESC_R"
/// Label for data resource type.
#define LSR_TYPE_DATA "DATA_R"

/// Determine if an IRI is an LSR resource.
#define LSR_IS_RSRC_IRI(term) \
    (LSUP_IS_IRI (term) && strstr ((term)->data, LSR_RSRC_PFX) == (term)->data)


/*
 * Data types.
 */

/// LS identifier type.
typedef char LSR_id[UUIDSTR_SIZE];

/// Term to key hash map.
typedef struct hashmap LSR_TermMap;

/// Resource flag type.
typedef enum res_flags_t {
    LSR_RS_MANAGED          = 1 << 0,       ///< Managed by the repo.
    LSR_RS_DIRTY            = 1 << 1,       ///< Dirty buffer.
} LSR_ResFlags;


/*
 * Global variables.
 */

/// Whether the environment is initialized.
extern bool LSR_is_init;

/// Managed predicates.
extern LSR_TermMap *LSR_managed_preds;
/// Managed RDF types.
extern LSR_TermMap *LSR_managed_types;


/*
 * API.
 */

/** @brief Initialize LSUP and LSR environments.
 *
 * This function is idempotent.
 */
LSUP_rc LSR_init (void);


/** @brief Tear down LSUP and LSR environments.
 *
 * This function is idempotent. It is also called automatically at the end of
 * a program (`atexit()`).
 */
void LSR_done (void);


/** @brief Create a new URN term from a resource ID and optional fragment.
 *
 * @param[in] id Resource ID.
 *
 * @param[in] frag Fragment to add to the URN. If not NULL, it is appended to
 *  the URN and an additional `#` character.
 *
 * @return New term. The default namespace map is associated with the term.
 *  It should be freed with #LSUP_term_free().
 */
inline LSUP_Term *LSR_id_to_urn (const uuid_t id, const char *frag)
{
    char id_str[UUID_STR_LEN];
    uuid_unparse_lower (id, id_str);
    char *urn_str;

    if (frag) {
        urn_str = malloc (
                strlen (LSR_RSRC_PFX) + UUID_STR_LEN + strlen (frag) + 2);
        if (! urn_str) return NULL;
        sprintf (urn_str, "%s%s#%s", LSR_RSRC_PFX, id_str, frag);
    } else {
        urn_str = malloc (strlen (LSR_RSRC_PFX) + UUID_STR_LEN + 1);
        if (! urn_str) return NULL;
        sprintf (urn_str, "%s%s", LSR_RSRC_PFX, id_str);
    }

    LSUP_Term *urn = LSUP_iriref_new (urn_str, LSUP_default_env->nsm);
    free (urn_str);

    return urn;
}

#endif /* _LSR_CODE_H */
